From 9d0aa7f2bbe2d1881bfd06d8f38d6f4fcd4c3679 Mon Sep 17 00:00:00 2001 From: robertl Date: Thu, 10 Jul 2003 06:02:12 +0000 Subject: [PATCH] Sketch in (crude) gpilots code so someone else can finish it. --- gpsbabel/Makefile | 2 +- gpsbabel/defs.h | 2 + gpsbabel/gpilots.c | 494 +++++++++++++++++++++++++++++++++++++++++++++ gpsbabel/util.c | 43 ++++ gpsbabel/vecs.c | 7 + 5 files changed, 547 insertions(+), 1 deletion(-) create mode 100644 gpsbabel/gpilots.c diff --git a/gpsbabel/Makefile b/gpsbabel/Makefile index eec76d66f..861f73517 100644 --- a/gpsbabel/Makefile +++ b/gpsbabel/Makefile @@ -5,7 +5,7 @@ INSTALL_TARGETDIR=/usr/local/ FMTS=magproto.o gpx.o geo.o mapsend.o mapsource.o \ gpsutil.o pcx.o cetus.o copilot.o gpspilot.o magnav.o \ psp.o holux.o garmin.o tmpro.o tpg.o \ - xcsv.o gcdb.o tiger.o internal_styles.o easygps.o quovadis.o + xcsv.o gcdb.o tiger.o internal_styles.o easygps.o quovadis.o gpilots.o FILTERS=position.o duplicate.o diff --git a/gpsbabel/defs.h b/gpsbabel/defs.h index e176e9c2f..5d4e3790d 100644 --- a/gpsbabel/defs.h +++ b/gpsbabel/defs.h @@ -288,6 +288,8 @@ void *xmalloc(size_t size); void *xrealloc(void *p, size_t s); void xfree(void *mem); char *xstrdup(const char *s); +char *xstrndup(const char *s, size_t n); +char *xstrndupt(const char *s, size_t n); char *xstrappend(char *src, const char *new); #define xxcalloc(nmemb, size, file, line) xcalloc(nmemb, size) #define xxmalloc(size, file, line) xmalloc(size) diff --git a/gpsbabel/gpilots.c b/gpsbabel/gpilots.c new file mode 100644 index 000000000..e84ea4f1b --- /dev/null +++ b/gpsbabel/gpilots.c @@ -0,0 +1,494 @@ +/* + Read and write GPilotS files. + + Copyright (C) 2003 Robert Lipe, robertlipe@usa.net + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA + + */ + +#include "defs.h" +#include "coldsync/palm.h" +#include "coldsync/pdb.h" + +#define MYNAME "GPilotS" +#define MYWPT 0x57707473 /* Wpts */ +#define MYTRK 0x54726b73 /* Trks */ +#define MYRTE 0x57707473 /* Wpts */ +#define MYCREATOR 0x4750696c /* GPil */ + + +/* + * Structures grafted from http://www.cru.fr/perso/cc/GPilotS/ + */ + +typedef struct +{ + long lat; /* latitude in semicircles */ + long lon; /* longitude in semicircles */ +} +Semicircle_Type; + +typedef struct +{ + unsigned char ident[6]; /* identifier */ + unsigned char lat[4]; /* position */ + unsigned char lon[4]; /* position */ + unsigned char unused[4]; /* should be set to zero */ + unsigned char cmnt[40]; /* comment */ + unsigned char smbl; /* symbol id */ + unsigned char dspl; /* display option */ +} D103_Wpt_Type; + + +typedef struct /* structure de waypoint "interne" */ +{ + unsigned char ident[51]; /* identifier (50 + '0') */ + Semicircle_Type posn; /* position (common to all Garmin types) */ + unsigned char cmnt[51]; /* comment (50 + '0') */ + float dst; /* proximity distance */ + float alt; /* altitude */ + int smbl; /* symbol id */ + unsigned char dspl; /* display option */ + unsigned char color; /* color */ +} +Custom_Wpt_Type; + +typedef struct /* internal track header */ +{ + char name[256]; /* nom du groupe de trackpoints */ + unsigned char dspl; /* display on the map ? */ + unsigned char color; /* color */ + unsigned char type; /* type of following track points */ + unsigned char number[4]; /* number of track points */ + unsigned char latmin[4]; /* latitude min */ + unsigned char latmax[4]; /* latitude max */ + unsigned char lonmin[4]; /* longitude min */ + unsigned char lonmax[4]; /* longitude max */ +} +Custom_Trk_Hdr_Type; + +typedef struct +{ + unsigned char lat[4]; /* position */ + unsigned char lon[4]; /* position */ + unsigned char time[4]; + unsigned char alt[4]; + unsigned char new_trk; +} Custom_Trk_Point_Type; + +struct record +{ + struct { + unsigned char type; + unsigned short size; + unsigned int version; + } header; + union { + D103_Wpt_Type d103; + Custom_Wpt_Type CustWpt; + Custom_Trk_Hdr_Type CustTrkHdr; +#if LATER + Custom_Rte_Hdr_Type CustRteHdr; +#endif + }; +}; + + +#if 0 +struct record { + + char type; + + char readonly; + + pdb_32 latitude; /* Big endian, degrees*1e7, s=negative */ + pdb_32 longitude; /* same as lat; w=negative */ + pdb_32 elevation; /* Big endian, meters*100. blank=-1e8 */ + + pdb_16 year; /* sample time, UTC */ + unsigned char mon; + unsigned char day; + unsigned char hour; + unsigned char min; + unsigned char sec; + + /* accuracy and precision information for use where applicable */ + char sat; /* ff if averaged or unknown */ + pdb_16 pdop; /* pdop * 100 */ + pdb_16 hdop; + pdb_16 vdop; + pdb_16 dgpstime; + pdb_32 dgpsstn; + pdb_32 avgtime; + pdb_32 avgite; + + pdb_16 dopmask; + pdb_16 elevmask; + + pdb_16 radius; + pdb_32 distance; + + pdb_16 vyear; /* date visited */ + unsigned char vmon; + unsigned char vday; + unsigned char vhour; + unsigned char vmin; + unsigned char vsec; + + char flagged; + + pdb_32 icon; + pdb_16 category; +}; +#endif + +static FILE *file_in; +static FILE *file_out; +static const char *out_fname; +struct pdb *opdb; +struct pdb_record *opdb_rec; + +static char *dbname = NULL; + +static +arglist_t my_args[] = { + {"dbname", &dbname, "Database name"}, + {0, 0, 0} +}; + +static void +rd_init(const char *fname, const char *args) +{ + file_in = fopen(fname, "rb"); + if (file_in == NULL) { + fatal(MYNAME ": Cannot open %s for reading\n", fname); + } +} + +static void +rd_deinit(void) +{ + fclose(file_in); + if ( dbname ) { + xfree(dbname); + dbname = NULL; + } +} + +static void +wr_init(const char *fname, const char *args) +{ + file_out = fopen(fname, "wb"); + out_fname = fname; + if (file_out == NULL) { + fatal(MYNAME ": Cannot open %s for writing\n", fname); + } +} + +static void +wr_deinit(void) +{ + fclose(file_out); + if ( dbname ) { + xfree(dbname); + dbname = NULL; + } +} + +static void +data_read(void) +{ + struct record *rec; + struct pdb *pdb; + struct pdb_record *pdb_rec; + char *vdata; + route_head *track_head; + + if (NULL == (pdb = pdb_Read(fileno(file_in)))) { + fatal(MYNAME ": pdb_Read failed\n"); + } + + if (pdb->creator != MYCREATOR) { + fatal(MYNAME ": Not a %s file.\n", MYNAME); + } + + switch(pdb->type) { + case MYWPT: + /* blah */ + break; + case MYTRK: + /* blah */ + break; + default: + fatal(MYNAME ": Unknown file type 0x%x\n", pdb->type); + } + + for(pdb_rec = pdb->rec_index.rec; pdb_rec; pdb_rec=pdb_rec->next) { + waypoint *wpt_tmp; + Custom_Trk_Point_Type *tp; + int lat; + int lon; + int sz; + + wpt_tmp = xcalloc(sizeof(*wpt_tmp),1); + + rec = (struct record *) pdb_rec->data; + switch(rec->header.type) { + /* + * G103Type + */ + case 4: + wpt_tmp->shortname = xstrndupt(rec->d103.cmnt, sizeof(rec->d103.ident)); + wpt_tmp->description = xstrndupt(rec->d103.cmnt, sizeof(rec->d103.cmnt)); + /* This is odd. This is a Palm DB file, + * yet the data appears to be little endian, + * not appropriate the the actual Palm. + */ + lon = le_read32(&rec->d103.lon); + lat = le_read32(&rec->d103.lat); + wpt_tmp->position.longitude.degrees = lon / 2147483648.0 * 180.0; + wpt_tmp->position.latitude.degrees = lat / 2147483648.0 * 180.0; + waypt_add(wpt_tmp); + break; + /* + * CustomTrkHdr + */ + case 101: + track_head = route_head_alloc(); + route_add_head(track_head); + track_head->rte_name = xstrndup(rec->CustTrkHdr.name, sizeof(rec->CustTrkHdr.name)); + sz = be_read32(&rec->CustTrkHdr.number); + tp = (Custom_Trk_Point_Type *) ((char *) pdb_rec->data + sizeof(rec->CustTrkHdr)); + /* FIXME: This is incomplete and probably wrong */ + while (sz--) { + wpt_tmp = xcalloc(sizeof(*wpt_tmp),1); + lon = le_read32(&tp->lon); + lat = le_read32(&tp->lat); + wpt_tmp->position.longitude.degrees = lon / 2147483648.0 * 180.0; + wpt_tmp->position.latitude.degrees = lat / 2147483648.0 * 180.0; + route_add_wpt(track_head, wpt_tmp); + tp++; + } + + } +#if 0 + if ( be_read32(&rec->elevation) == -100000000 ) { + wpt_tmp->position.altitude.altitude_meters = unknown_alt; + } + else { + wpt_tmp->position.altitude.altitude_meters = be_read32(&rec->elevation) / 100.0; + } + + wpt_tmp->position.longitude.degrees = be_read32(&rec->longitude) / 10000000.0; + wpt_tmp->position.latitude.degrees = be_read32(&rec->latitude) / 10000000.0; + + if (be_read16(&rec->year) != 0xff) { + struct tm tm = {0}; + + tm.tm_min = rec->min; + tm.tm_hour = rec->hour; + tm.tm_mday = rec->day; + tm.tm_mon = rec->mon - 1; + tm.tm_year = be_read16(&rec->year) - 1900; + + wpt_tmp->creation_time = mktime(&tm); + + } + + vdata = (char *) pdb_rec->data + sizeof(*rec); + + wpt_tmp->shortname = xstrdup(vdata); + vdata = vdata + strlen(vdata) + 1; + + wpt_tmp->description = xstrdup(vdata); + vdata = vdata + strlen(vdata) + 1; + + wpt_tmp->notes = xstrdup(vdata); +#endif + + } + free_pdb(pdb); +} + + +static void +my_writept(waypoint *wpt) +{ + struct record *rec; + static int ct; + struct tm *tm; + char *vdata; + + rec = xcalloc(sizeof(*rec)+1018,1); +#if 0 + if (wpt->creation_time) { + tm = gmtime(&wpt->creation_time); + rec->min = tm->tm_min; + rec->hour = tm->tm_hour; + rec->sec = tm->tm_sec; + rec->day = tm->tm_mday; + rec->mon = tm->tm_mon + 1; + be_write16( &rec->year, tm->tm_year + 1900); + } else { + rec->min = 0xff; + rec->hour = 0xff; + rec->sec = 0xff; + rec->day = 0xff; + rec->mon = 0xff; + be_write16(&rec->year, 0xff); + } + + be_write32(&rec->longitude, wpt->position.longitude.degrees * 10000000.0); + be_write32(&rec->latitude, wpt->position.latitude.degrees * 10000000.0); + if ( wpt->position.altitude.altitude_meters == unknown_alt ) { + be_write32(&rec->elevation, -100000000U); + } + else { + be_write32(&rec->elevation, wpt->position.altitude.altitude_meters * 100.0); + } + + be_write16( &rec->pdop, 0xffff ); + be_write16( &rec->hdop, 0xffff ); + be_write16( &rec->vdop, 0xffff ); + be_write16( &rec->dgpstime, 0xffff ); + be_write32( &rec->distance, 0xffffffff ); + + rec->vmin = 0xff; + rec->vhour = 0xff; + rec->vsec = 0xff; + rec->vday = 0xff; + rec->vmon = 0xff; + be_write16(&rec->vyear, 0xff); + + rec->sat = 0xff; + + vdata = (char *)rec + sizeof(*rec); + if ( wpt->shortname ) { + strncpy( vdata, wpt->shortname, 16 ); + vdata[15] = '\0'; + } + else { + vdata[0] ='\0'; + } + vdata += strlen( vdata ) + 1; + + if ( wpt->description ) { + strncpy( vdata, wpt->description, 501 ); + vdata[500] = '\0'; + } + else { + vdata[0] ='\0'; + } + vdata += strlen( vdata ) + 1; + + if ( wpt->notes ) { + strncpy( vdata, wpt->notes, 501 ); + vdata[500] = '\0'; + } + else { + vdata[0] ='\0'; + } + vdata += strlen( vdata ) + 1; +#endif + opdb_rec = new_Record (0, 2, ct++, vdata-(char *)rec, (const ubyte *)rec); + + if (opdb_rec == NULL) { + fatal(MYNAME ": libpdb couldn't create record\n"); + } + + if (pdb_AppendRecord(opdb, opdb_rec)) { + fatal(MYNAME ": libpdb couldn't append record\n"); + } + xfree(rec); +} + +struct hdr{ + char *wpt_name; + waypoint *wpt; +}; + +static +int +compare(const void *a, const void *b) +{ + const struct hdr *wa = a; + const struct hdr *wb = b; + + return strcmp(wa->wpt->shortname, wb->wpt->shortname); +} + +static void +data_write(void) +{ + int i, ct = waypt_count(); + struct hdr *htable, *bh; + queue *elem, *tmp; + extern queue waypt_head; + waypoint *waypointp; + + if (NULL == (opdb = new_pdb())) { + fatal (MYNAME ": new_pdb failed\n"); + } + + if ( dbname ) { + strncpy( opdb->name, dbname, PDB_DBNAMELEN ); + } + else { + strncpy(opdb->name, out_fname, PDB_DBNAMELEN); + } + opdb->name[PDB_DBNAMELEN-1] = 0; + opdb->attributes = PDB_ATTR_BACKUP; + opdb->ctime = opdb->mtime = time(NULL) + 2082844800U; +#if SOON + opdb->type = MYTYPE; /* CWpt */ + opdb->creator = MYCREATOR; /* cGPS */ +#endif + opdb->version = 1; + + /* + * All this is to sort by waypoint names before going to Cetus. + * Turns out plain old strcmp will do the trick... + */ + + htable = xmalloc(ct * sizeof(*htable)); + bh = htable; + + QUEUE_FOR_EACH(&waypt_head, elem, tmp) { + waypointp = (waypoint *) elem; + bh->wpt = waypointp; + bh->wpt_name = waypointp->shortname; + bh ++; + } + qsort(htable, ct, sizeof(*bh), compare); + + for (i=0;i sz) { + newlen = sz; + } + + newstr = xmalloc(newlen + 1); + memcpy(newstr, str, newlen); + newstr[newlen] = 0; + + return newstr; +} + +/* + * Lazily trim whitespace (though not from allocated version) + * while copying. + */ +char * +xstrndupt(const char *str, size_t sz) +{ + size_t newlen; + char *newstr; + + newlen = strlen(str); + if (newlen > sz) { + newlen = sz; + } + + newstr = xmalloc(newlen + 1); + memcpy(newstr, str, newlen); + rtrim(newstr); + + return newstr; +} + void * #ifdef DEBUG_MEM XREALLOC(void *p, size_t s, DEBUG_PARAMS ) diff --git a/gpsbabel/vecs.c b/gpsbabel/vecs.c index 4f5fce710..2f2833901 100644 --- a/gpsbabel/vecs.c +++ b/gpsbabel/vecs.c @@ -51,6 +51,7 @@ extern ff_vecs_t tmpro_vecs; extern ff_vecs_t gcdb_vecs; extern ff_vecs_t easygps_vecs; extern ff_vecs_t quovadis_vecs; +extern ff_vecs_t gpilots_vecs; static vecs_t vec_list[] = { @@ -181,6 +182,12 @@ vecs_t vec_list[] = { "Quovadis", NULL }, + { + &gpilots_vecs, + "gpilots", + "GpilotS", + NULL + }, { NULL, NULL, -- 2.30.2